﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections;
using System.Drawing;
using System.IO;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Logging;
using Microsoft.Build.Execution;

namespace ICeFramework.Utilities.VisualStudio
{
    public class MSBuilder
    {
        public delegate void BuildLogHandler(string message, Color color);

        public event BuildLogHandler BuildLog;

        private Color _color;

        private string _projectFile;
        public string ProjectFile
        {
            get { return _projectFile; }
            set { _projectFile = value; }
        }

        private string _compiledAssembly;
        public string CompiledAssembly
        {
            get { return _compiledAssembly; }
        }

        public MSBuilder(string projectFile)
        {
            _projectFile = projectFile;
        }

        //public bool Compile(out string[] outputFiles)
        //{
        //    bool result = false;
        //    List<string> compiledFiles = new List<string>();
        //    _compiledAssembly = string.Empty;

        //    //BuildPropertyGroup group = new BuildPropertyGroup();
        //    //group.SetProperty("Configuration", "Release");
        //    ProjectCollection projectList = new ProjectCollection();
        //   //projectList.GetLoadedProjects(
        //    //projectList.
        //    //projectList.l
        //    //Engine engine = new Engine(group);
        //    try
        //    {
        //        Microsoft.Build.Evaluation.Project project = projectList.LoadProject(_projectFile);
        //        if (project == null)
        //        {
        //            project = new Microsoft.Build.Evaluation.Project(_projectFile, null, null, projectList); // projectList.CreateNewProject();
        //            project.IsBuildEnabled = true;
        //            //project.
        //            //project.Load(_projectFile);

        //        }

        //        IDictionary outFiles = new Hashtable();
        //        //project.Build(null, outFiles, BuildSettings.None);
        //        //Logger lg
        //        //ICeFramework.Utilities.VisualStudio.ConsoleLogger logger = new ICeFramework.Utilities.VisualStudio.ConsoleLogger(LoggerVerbosity.Normal, OnBuildLogBase, OnColorSet, OnColorReset);
        //        //engine.RegisterLogger(logger);
        //        //result = engine.BuildProjectFile(_projectFile);

        //        //if (result)
        //        //{
        //        //    foreach (object key in outFiles.Keys)
        //        //    {
        //        //        if (key.ToString() == "Build")
        //        //        {
        //        //            object[] tasks = (object[])outFiles[key];
        //        //            foreach (object task in tasks)
        //        //            {
        //        //                _compiledAssembly = task.ToString();
        //        //            }
        //        //        }
        //        //    }
        //        //    List<string> files = GetOutputFiles(Path.GetDirectoryName(_compiledAssembly));
        //        //    foreach (string file in files)
        //        //    {
        //        //        compiledFiles.Add(file);
        //        //    }
        //        //}
        //        //engine.UnregisterAllLoggers();
        //        //engine.UnloadAllProjects();
        //    }
        //    catch (Exception ex)
        //    {
        //        OnBuildLog(ex.ToString(), Color.Red);
        //    }
        //    finally
        //    {
        //        //if (engine != null)
        //        //{
        //        //    engine.Shutdown();
        //        //}
        //    }

        //    outputFiles = compiledFiles.ToArray<string>();
        //    //outputFiles = new string[0];
        //    return result;
        //}

        public bool Compile(string outputPath, out string[] outputFiles, string configurationName = "Debug", string platform = "x86")
        {
            bool result = false;
            List<string> compiledFiles = new List<string>();
            _compiledAssembly = string.Empty;
            outputFiles = new string[0];
            try
            {
                using (ProjectCollection projectCollection = new ProjectCollection())
                {
                    Dictionary<string, string> GlobalProperty = new Dictionary<string, string>();
                    GlobalProperty.Add("Configuration", configurationName);
                    GlobalProperty.Add("Platform", platform);
                    GlobalProperty.Add("OutputPath", outputPath);
                    BuildRequestData buildRequest = new BuildRequestData(_projectFile, GlobalProperty, null, new string[] { "Build" }, null);
                    BuildResult buildResult = BuildManager.DefaultBuildManager.Build(new BuildParameters(projectCollection), buildRequest);
                    if (buildResult.OverallResult == BuildResultCode.Failure)
                    {
                        //projectCollection.LoadedProjects.ToList()[1].
                        throw buildResult.Exception;
                        //buildResult.ResultsByTarget["a"].ResultCode = TargetResultCode.
                    }
                    outputFiles = GetOutputFiles(outputPath).ToArray();
                    result = true;
                }
            }
            catch (Exception ex)
            {
                OnBuildLog(ex.ToString(), Color.Red);
            }
            return result;
        }

        public bool Compile(out string[] outputFiles)
        {
            bool result = false;
            List<string> compiledFiles = new List<string>();
            _compiledAssembly = string.Empty;

            //BuildPropertyGroup group = new BuildPropertyGroup();
            //group.SetProperty("Configuration", "Release");
            ProjectCollection projectList = new ProjectCollection();
            //projectList.GetLoadedProjects(
            //projectList.
            //projectList.l
            //Engine engine = new Engine(group);
            try
            {
                string projectFileName = @"\visual studio 2010\Projects\ConsoleApplication1\ConsoleApplication1.sln";

                ProjectCollection pc = new ProjectCollection();
                ProjectInstance prj = new ProjectInstance(projectFileName);
                
                Dictionary<string, string> GlobalProperty = new Dictionary<string, string>();

                GlobalProperty.Add("Configuration", "Debug");

                GlobalProperty.Add("Platform", "x86");

                //Here, we set the property

                GlobalProperty.Add("OutputPath", @"D:\Output");

                BuildRequestData BuidlRequest = new BuildRequestData(projectFileName, GlobalProperty, null, new string[] { "Build" }, null);
                BuildResult buildResult = BuildManager.DefaultBuildManager.Build(new BuildParameters(pc), BuidlRequest);
                



                Microsoft.Build.Evaluation.Project project = projectList.LoadProject(_projectFile);
                if (project == null)
                {
                    project = new Microsoft.Build.Evaluation.Project(_projectFile, null, null, projectList); // projectList.CreateNewProject();
                    project.IsBuildEnabled = true;
                    //project.
                    //project.Load(_projectFile);

                }

                IDictionary outFiles = new Hashtable();
                //project.Build(null, outFiles, BuildSettings.None);
                //Logger lg
                //ICeFramework.Utilities.VisualStudio.ConsoleLogger logger = new ICeFramework.Utilities.VisualStudio.ConsoleLogger(LoggerVerbosity.Normal, OnBuildLogBase, OnColorSet, OnColorReset);
                //engine.RegisterLogger(logger);
                //result = engine.BuildProjectFile(_projectFile);

                //if (result)
                //{
                //    foreach (object key in outFiles.Keys)
                //    {
                //        if (key.ToString() == "Build")
                //        {
                //            object[] tasks = (object[])outFiles[key];
                //            foreach (object task in tasks)
                //            {
                //                _compiledAssembly = task.ToString();
                //            }
                //        }
                //    }
                //    List<string> files = GetOutputFiles(Path.GetDirectoryName(_compiledAssembly));
                //    foreach (string file in files)
                //    {
                //        compiledFiles.Add(file);
                //    }
                //}
                //engine.UnregisterAllLoggers();
                //engine.UnloadAllProjects();
            }
            catch (Exception ex)
            {
                OnBuildLog(ex.ToString(), Color.Red);
            }
            finally
            {
                //if (engine != null)
                //{
                //    engine.Shutdown();
                //}
            }

            outputFiles = compiledFiles.ToArray<string>();
            //outputFiles = new string[0];
            return result;
        }

        private List<string> GetOutputFiles(string dir)
        { 
            List<string> files = new List<string>();
            foreach (string fi in Directory.GetFiles(dir))
            {
                files.Add(fi);
            }
            foreach (string childDir in Directory.GetDirectories(dir))
            {
                List<string> childrenFiles = GetOutputFiles(childDir);
                foreach (string childrenFile in childrenFiles)
                {
                    files.Add(childrenFile);
                }
            }
            return files;
        }



        private void OnBuildLogBase(string message)
        {
            OnBuildLog(message, _color);
        }

        public void OnBuildLog(string message, Color color)
        {
            if (BuildLog != null)
            {
                BuildLog(message, color);
            }
        }

        private void OnColorSet(ConsoleColor color)
        {
            _color = Color.FromName(color.ToString());
        }

        private void OnColorReset()
        {
            _color = Color.Black;
        }
    }
}
